package lib.self.ex.fragment;

import android.app.Activity;
import android.app.Service;
import android.content.Intent;
import android.os.Build.VERSION;
import android.os.Build.VERSION_CODES;
import android.os.Bundle;
import android.view.LayoutInflater;
import android.view.View;
import android.view.View.OnClickListener;
import android.view.ViewGroup;
import android.view.ViewTreeObserver;
import android.view.ViewTreeObserver.OnPreDrawListener;

import androidx.annotation.ColorInt;
import androidx.annotation.DrawableRes;
import androidx.annotation.IdRes;
import androidx.annotation.LayoutRes;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.annotation.StringRes;
import androidx.fragment.app.Fragment;

import com.gyf.immersionbar.ImmersionBar;

import lib.self.LogMgr;
import lib.self.R;
import lib.self.ex.decor.NewDecorView;
import lib.self.ex.decor.TitleBarEx;
import lib.self.ex.dialog.DialogEx;
import lib.self.ex.instance.LoadingDialog;
import lib.self.ex.interfaces.IFitParams;
import lib.self.ex.interfaces.IInitialize;
import lib.self.ex.interfaces.INetwork;
import lib.self.ex.interfaces.IOption;
import lib.self.ex.interfaces.OnRetryClickListener;
import lib.self.network.NetworkExecutor;
import lib.self.network.bean.NetworkListener;
import lib.self.network.bean.NetworkRequest;
import lib.self.network.bean.NetworkResponse;
import lib.self.network.error.NetError;
import lib.self.params.TitleBarState;
import lib.self.params.TitleBarState.ITitleBarState;
import lib.self.params.ViewState.IViewState;
import lib.self.stats.Stats;
import lib.self.util.autoFit.FitDpUtil;
import lib.self.util.autoFit.FitViewParamsUtil;
import lib.self.util.view.ViewUtil;
import lib.self.utils.DeviceUtil;
import lib.self.utils.NetUtil;
import lib.self.utils.ToastUtil;
import lib.self.utils.UiUtil;


/**
 * description: Fragment父类
 * author: Steven Xiao
 * date: 2018/10/17
 */
public abstract class NewFragmentEx extends Fragment implements IInitialize, INetwork, IOption, IFitParams, OnRetryClickListener, OnClickListener {

    protected final String TAG = getClass().getSimpleName();

    private View mOuterView;//最外层的View
    private View mTopView;
    private NewDecorView mDecorView;

    private boolean mInitComplete = false;

    private NetworkExecutor mNetworkExecutor;

    private boolean mIsVisible = false;

    private boolean mIsCreateView = false;
    private boolean mIsVisibleToUser = false;

    private DialogEx mLoadingDialog;

    private NewFragmentEx mFragRoot;
    private NewFragmentEx mFragChild;

    protected ImmersionBar mImmersionBar;

    @Nullable
    @Override
    public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
        if (mOuterView != null) {
            setOnRetryClickListener(this);
            return mOuterView;
        } else {
            mOuterView = inflate(getParentContentViewId(), null);
            mDecorView = mOuterView.findViewById(R.id.fragment_view_decor);
            mTopView = mOuterView.findViewById(R.id.top_view);
            mDecorView.setTitleBarState(getTitleBarState());

            if (useFullScreen() && DeviceUtil.getSDKVersion() > VERSION_CODES.JELLY_BEAN_MR2) {
                UiUtil.setStatusBar(mTopView, getStatusBarBackgroundColor());
            }

            initDecorView();

            if (useLazyLoad()) {
                if (mIsVisibleToUser) {
                    init();
                }
            } else {
                init();
            }

            setOnRetryClickListener(this);
            mIsCreateView = true;
            return mOuterView;
        }
    }

    @Override
    public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState) {
        super.onViewCreated(view, savedInstanceState);
        if (useFullScreen()) {
            setStatusBar();
        }
    }

    /**
     * ViewPager专用
     *
     * @param isVisibleToUser
     */
    @Override
    public void setUserVisibleHint(boolean isVisibleToUser) {
        super.setUserVisibleHint(isVisibleToUser);
        mIsVisibleToUser = isVisibleToUser;
        if (mIsCreateView) {
            handleVisibleChanged(isVisibleToUser);
        }
    }

    /**
     * 普通方法使用
     *
     * @param hidden
     */
    @Override
    public void onHiddenChanged(boolean hidden) {
        if (mIsCreateView) {
            handleVisibleChanged(!hidden);
        }
    }

    protected boolean getVisible() {
        return mIsVisible;
    }

    private void handleVisibleChanged(boolean visible) {
        mIsVisible = visible;

        if (useLazyLoad()) {
            if (visible) {
                if (!mInitComplete) {
                    init();
                }
            }
        }

        if (visible) {
            onVisible();
            if (useFullScreen()) {
                setStatusBar();
            }
            Stats.onFragmentVisible(TAG);
        } else {
            onInvisible();
            Stats.onFragmentInVisible(TAG);
        }
    }

    /**
     * fragment可见回调
     */
    protected void onVisible() {
    }

    /**
     * fragment不可见回调
     */
    protected void onInvisible() {
    }

    protected void setStatusBar() {
        mImmersionBar = ImmersionBar.with(this);
        mImmersionBar.keyboardEnable(true).navigationBarWithKitkatEnable(false).init();
    }

    public int getParentContentViewId() {
        return R.layout.fragment_ex;
    }

    @Override
    public int getContentHeaderViewId() {
        return 0;
    }

    private void initDecorView() {
        mDecorView.setContentView(getContentViewId(), getContentHeaderViewId());
        autoFitAll(mDecorView);

        if (useLazyLoad()) {
            initData();
            initTitleBar();
        }
    }

    /**
     * 使用全屏模式--沉浸模式
     */
    protected boolean useFullScreen() {
        return false;
    }

    @ColorInt
    protected int getStatusBarBackgroundColor() {
        return 0;
    }

    /**
     * 使用懒加载-----用于viewpager
     *
     * @return
     */
    protected boolean useLazyLoad() {
        return false;
    }

    private void init() {
        if (!useLazyLoad()) {
            initData();
            initTitleBar();
        }

        findViews();
        setViewsValue();
        mInitComplete = true;
        afterInitCompleted();
    }

    /**
     * 加载完成
     */
    protected void afterInitCompleted() {
    }

    protected @ITitleBarState int getTitleBarState() {
        return TitleBarState.KLinear;
    }

    protected View inflate(@LayoutRes int resource, @Nullable ViewGroup root) {
        return getLayoutInflater().inflate(resource, root);
    }

    /**
     * http回调
     */
    @Override
    public Object onNetworkResponse(int id, NetworkResponse nr) {
        return null;
    }

    @Override
    public void onNetworkSuccess(int id, Object result) {
    }

    @Override
    public void onNetworkError(int id, NetError error) {
        LogMgr.d(TAG, "onNetworkError(): " + "tag = [" + id + "], error = [" + error.message() + "]");
    }

    @Override
    public void onNetworkProgress(int id, float progress, long totalSize) {
    }

    @Override
    public void cancelNetworkRequest(int tag) {
        if (mNetworkExecutor != null) {
            mNetworkExecutor.cancel(tag);
        }
    }

    @Override
    public void cancelAllNetworkRequest() {
        if (mNetworkExecutor != null) {
            mNetworkExecutor.cancelAll();
        }
    }

    @Override
    public void exeNetworkRequest(int tag, NetworkRequest request) {
        exeNetworkRequest(tag, request, this);
    }

    @Override
    public void exeNetworkRequest(int tag, NetworkRequest request, NetworkListener listener) {
        if (isRemoving()) {
            return;
        }
        if (mNetworkExecutor == null) {
            mNetworkExecutor = new NetworkExecutor(getClass().getName(), this);
        }
        mNetworkExecutor.execute(tag, request, listener);
    }

    protected TitleBarEx getTitleBar() {
        return mDecorView.getTitleBar();
    }

    /**
     * 设置视图状态
     *
     * @param state
     */
    public void setViewState(@IViewState int state) {
        mDecorView.setViewState(state);
    }

    public boolean isActivityFinishing() {
        return getActivity() == null || getActivity().isFinishing();
    }

    protected <T extends View> T findViewById(@IdRes int id) {
        return (T) mOuterView.findViewById(id);
    }

    /**
     * 用于header footer等
     */
    public <T extends View> T findChildView(View headerView, @IdRes int childId) {
        return (T) headerView.findViewById(childId);
    }

    @Override
    public void showView(View view) {
        ViewUtil.showView(view);
    }

    @Override
    public void hideView(View view) {
        ViewUtil.hideView(view);
    }

    @Override
    public void goneView(View view) {
        ViewUtil.goneView(view);
    }

    @Override
    public void startActivity(Class<? extends Activity> cls) {
        startActivity(new Intent(getActivity(), cls));
    }

    public void startActivity(Class<? extends Activity> cls, Bundle extras) {
        Intent intent = new Intent(getActivity(), cls);
        intent.putExtras(extras);
        startActivity(intent);
    }

    @Override
    public void startActivityForResult(Class<? extends Activity> cls, int requestCode) {
        startActivityForResult(new Intent(getActivity(), cls), requestCode);
    }

    @Override
    public void startActivityForResult(Intent intent, int requestCode) {
        startActivityForResult(intent, requestCode, this);
    }

    private void startActivityForResult(Intent intent, int requestCode, NewFragmentEx fragChild) {
        findRootFragment();
        if (mFragRoot != null) {
            // 不是root才需要保存
            mFragRoot.saveResponseChild(fragChild);
        }
        super.startActivityForResult(intent, requestCode);
    }

    public void startService(Class<? extends Service> cls) {
        Intent intent = new Intent(getActivity(), cls);
        if (VERSION.SDK_INT >= VERSION_CODES.O) {
            getActivity().startForegroundService(intent);
        } else {
            getActivity().startService(intent);
        }
    }

    public void startService(Intent intent) {
        if (VERSION.SDK_INT >= VERSION_CODES.O) {
            getActivity().startForegroundService(intent);
        } else {
            getActivity().startService(intent);
        }
    }

    /**
     * 保存响应的子frag
     *
     * @param fragment
     */
    public void saveResponseChild(NewFragmentEx fragment) {
        mFragChild = fragment;
    }

    /**
     * 得到根Fragment
     *
     * @return 如果有root则返回root, 本身是root则返回null
     */
    @Nullable
    public void findRootFragment() {
        if (mFragRoot == null) {
            mFragRoot = (NewFragmentEx) getParentFragment();
            if (mFragRoot != null) {
                // 有root frag
                while (mFragRoot.getParentFragment() != null) {
                    mFragRoot = (NewFragmentEx) mFragRoot.getParentFragment();
                }
            }
        }
    }


    /**
     * 需要在此判断发起请求的对象, 特意用final修饰防止重写
     *
     * @see {@link #onResultData(int, int, Intent)}
     */
    @Deprecated
    @Override
    public final void onActivityResult(int requestCode, int resultCode, Intent data) {
        if (mFragChild != null) {
            // 子frag发起的需要回调
            mFragChild.onResultData(requestCode, resultCode, data);
        } else {
            // 本身发起的
            onResultData(requestCode, resultCode, data);
        }
    }

    /**
     * 用来替换{@link #onActivityResult(int, int, Intent)}来接收跳转回调的消息处理
     *
     * @param requestCode
     * @param resultCode
     * @param data
     */
    protected void onResultData(int requestCode, int resultCode, Intent data) {
    }

    public void showToast(String text) {
        ToastUtil.showToast(getActivity(), text);
    }

    public void showToast(@StringRes int resId) {
        ToastUtil.showToast(getActivity(), resId);
    }

    @Override
    public int dpToPx(float dp) {
        return FitDpUtil.dpToPx(dp, getActivity());
    }

    @Override
    public void autoFitAll(View view) {
        FitViewParamsUtil.autoFitAll(view);
    }

    protected void setBackgroundColor(@ColorInt int color) {
        mDecorView.setBackgroundColor(color);
    }

    protected void setBackgroundResource(@DrawableRes int resId) {
        mDecorView.setBackgroundResource(resId);
    }

    @Override
    public void onDestroy() {
        super.onDestroy();

        cancelAllNetworkRequest();
        mNetworkExecutor = null;
    }

    protected Intent getIntent() {
        return getActivity().getIntent();
    }

    protected NewDecorView getDecorView() {
        return mDecorView;
    }

    protected boolean initComplete() {
        return mInitComplete;
    }

    protected void setOnRetryClickListener(OnRetryClickListener listener) {
        mDecorView.setOnRetryClickListener(listener);
    }

    /**
     * @return 获取页面状态
     */
    protected int getViewState() {
        return mDecorView.getViewState();
    }

    protected void setOnClickListener(@IdRes int id) {
        View view = findViewById(id);
        if (view != null) {
            view.setOnClickListener(this);
        }
    }

    protected void setOnClickListener(@IdRes int... ids) {
        for (int id : ids) {
            setOnClickListener(id);
        }
    }

    @Override
    public void onClick(View v) {
    }

    @Override
    public boolean onRetryClick() {
        if (!NetUtil.isNetworkEnable()) {
            showToast(R.string.toast_network_disconnect);
            return true;
        }
        return false;
    }

    /**
     * 初始化loading dialog
     */
    protected DialogEx initLoadingDialog() {
        DialogEx dialog = new LoadingDialog(getActivity());
        dialog.setOnCancelListener(dialog1 -> {
            cancelAllNetworkRequest();
            dismissLoadingDialog();
        });
        return dialog;
    }

    protected void showLoadingDialog() {
        if (!isActivityFinishing() && mDecorView != null) {
            if (mLoadingDialog == null) {
                mLoadingDialog = initLoadingDialog();
            }
            mLoadingDialog.show();
        }
    }

    protected void dismissLoadingDialog() {
        if (!isActivityFinishing() && mDecorView != null) {
            if (mLoadingDialog == null) {
                mLoadingDialog = initLoadingDialog();
            }
            mLoadingDialog.dismiss();
        }
    }

    protected void finish() {
        getActivity().finish();
    }

    /**
     * 解决java.lang.IllegalStateException: No activity
     * <p>产生原因:当第一次从一个Activity启动Fragment，然后再去启动子Fragment的时候，存在指向Activity的变量，
     * 但当退出这些Fragment之后回到Activity，然后再进入Fragment的时候，这个变量变成null
     * </p>
     * <p>
     * 解决方法:在Fragment被detached的时候去重置ChildFragmentManager
     * </p>
     */
    @Override
    public void onDetach() {
        super.onDetach();

//        try {
//            Field childFragmentManager = Fragment.class.getDeclaredField("mChildFragmentManager");
//            childFragmentManager.setAccessible(true);
//            childFragmentManager.set(this, null);
//        } catch (Exception e) {
//            LogMgr.e(TAG, "onDetach", e);
//        }
    }

    /***********************************
     * 有关DecorView的ViewTreeObserver的操作
     */

    /**
     * ViewTreeObserver是否Alive
     *
     * @return
     */
    protected boolean isViewTreeObserverAlive() {
        return mDecorView.getViewTreeObserver().isAlive();
    }

    protected ViewTreeObserver getViewTreeObserver() {
        return mDecorView.getViewTreeObserver();
    }

    protected boolean addOnPreDrawListener(OnPreDrawListener listener) {
        if (isViewTreeObserverAlive()) {
            getViewTreeObserver().addOnPreDrawListener(listener);
            return true;
        }
        return false;
    }

    protected void removeOnPreDrawListener(OnPreDrawListener listener) {
        getViewTreeObserver().removeOnPreDrawListener(listener);
    }
}
